package com.gpframework.module.module.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gpframework.common.enums.YesNoEnum;
import com.gpframework.common.utils.DateUtils;
import com.gpframework.common.utils.StringUtils;
import com.gpframework.module.manufacture.domain.GpDyeingFactory;
import com.gpframework.module.manufacture.domain.GpProductionDetails;
import com.gpframework.module.manufacture.domain.GpProductionScheduling;
import com.gpframework.module.manufacture.domain.GpWeightReductionRuleSetting;
import com.gpframework.module.manufacture.domain.vo.GpProductionDetailsVo;
import com.gpframework.module.manufacture.domain.vo.GpProductionSchedulingVo;
import com.gpframework.module.manufacture.service.IGpDyeingFactoryService;
import com.gpframework.module.manufacture.service.IGpProductionDetailsService;
import com.gpframework.module.manufacture.service.IGpWeightReductionRuleSettingService;
import com.gpframework.module.manufacture.service.impl.GpProductionDetailsServiceImpl;
import com.gpframework.module.manufacture.service.impl.GpProductionSchedulingServiceImpl;
import com.gpframework.module.module.domain.*;
import com.gpframework.module.module.domain.req.GpDeliveryNoteUpdate;
import com.gpframework.module.module.domain.vo.GpDeliveryNoteVo;
import com.gpframework.module.module.mapper.GpDeliveryNoteMapper;
import com.gpframework.module.module.service.IGpDeliveryNoteService;
import com.gpframework.module.module.service.IGpIncomingInspectWeightService;
import com.gpframework.module.module.service.IGpIncomingInspectWidthService;
import com.gpframework.module.module.service.IGpIncomingInspectYardVerifyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @ClassName GpDeliveryNote
 * @Author gpframework
 * @Date 2023-12-11
 * @Version 1.0.0
 * @Description 到货单Service业务层处理
 */
@Service
public class GpDeliveryNoteServiceImpl extends ServiceImpl<GpDeliveryNoteMapper, GpDeliveryNote> implements IGpDeliveryNoteService {

    @Autowired
    private GpProductionDetailsServiceImpl gpProductionDetailsService;

    @Autowired
    private GpProductionSchedulingServiceImpl gpProductionSchedulingService;

    @Autowired
    private  GpIncomingInspectServiceImpl gpIncomingInspectService;

    @Autowired
    private IGpDyeingFactoryService iGpDyeingFactoryService;

    @Autowired
    private IGpIncomingInspectYardVerifyService iGpIncomingInspectYardVerifyService;

    @Autowired
    private IGpIncomingInspectWidthService iGpIncomingInspectWidthService;

    @Autowired
    private IGpIncomingInspectWeightService iGpIncomingInspectWeightService;

    @Autowired
    private IGpProductionDetailsService iGpProductionDetailsService;


    @Autowired
    private IGpWeightReductionRuleSettingService iGpWeightReductionRuleSettingService;




    /**
     * @Description 查询列表返回VO 用于返回给前端的列表接口
     * @Author gpframework
     * @Date 2023-12-11
     * @Param [lqw]
     * @Return List<GpDeliveryNoteVo>
     */
    @Override
    public List<GpDeliveryNoteVo> listVo(QueryWrapper<GpDeliveryNote> lqw) {
        return this.baseMapper.listVo(lqw);
    }

    /**
     * @Description 通过查询详情VO 用于返回给前端的列详情接口
     * @Author gpframework
     * @Date 2023-12-11
     * @Param [id]
     * @Return GpDeliveryNoteVo
     */
    @Override
    public GpDeliveryNoteVo getVoById(Long id) {
        return this.baseMapper.getVo(id);
    }

    /**
     * 生成来料检验单
     * @param gpDeliveryNoteUpdate
     * @return
     */
    @Override
    @Transactional
    public boolean addIncomingInspect(GpDeliveryNoteUpdate gpDeliveryNoteUpdate) {
        List<Long> ids = gpDeliveryNoteUpdate.getIds();
        // 修改到货单生成来料状态
        this.update(new UpdateWrapper<GpDeliveryNote>().set("incoming_flag", YesNoEnum.YES.getKey()).in("id", ids));
        GpDeliveryNoteVo gpDeliveryNoteVo;

        GpProductionDetailsVo gpProductionDetailsVo;
        GpProductionSchedulingVo gpProductionSchedulingVo;
        List<GpIncomingInspect> gpIncomingInspectList =new ArrayList<>();
        Date now = new Date();
        for (Long id : ids) {

            gpDeliveryNoteVo = this.getVoById(id);
            if (gpDeliveryNoteVo == null) {
                continue;
            }
            GpIncomingInspect gpIncomingInspect = new GpIncomingInspect();
            if (StringUtils.isNotBlank(gpDeliveryNoteUpdate.getCreateBy())) {
                gpIncomingInspect.setCreateBy(gpDeliveryNoteUpdate.getCreateBy());
            }
            gpIncomingInspect.setSupplierName(gpDeliveryNoteVo.getSupplierName());
            gpIncomingInspect.setDyeingFactoryName(gpDeliveryNoteVo.getDyeingFactoryName());
            gpIncomingInspect.setBatchNo(gpDeliveryNoteVo.getBatchNo());
            gpIncomingInspect.setDyeVatNo(gpDeliveryNoteVo.getDyeVatNo());
            gpIncomingInspect.setBrandName(gpDeliveryNoteVo.getBrandName());
            gpIncomingInspect.setProductName(gpDeliveryNoteVo.getProductName());
            gpIncomingInspect.setColour(gpDeliveryNoteVo.getColour());
            gpIncomingInspect.setQuantity(gpDeliveryNoteVo.getQuantity());
            gpIncomingInspect.setTotalQuantity(gpDeliveryNoteVo.getTotalQuantity());
            gpIncomingInspect.setProductionApplicationId(gpDeliveryNoteVo.getProductionApplicationId());
            gpIncomingInspect.setProductionDetailsId(gpDeliveryNoteVo.getProductionDetailsId());
            gpIncomingInspect.setProductionSchedulingId(gpDeliveryNoteVo.getProductionSchedulingId());
            gpIncomingInspect.setDeliveryNoteId(gpDeliveryNoteVo.getId());
            gpIncomingInspect.setRemarks(gpDeliveryNoteVo.getRemarks());

            //打码规格 标签规格
            gpProductionDetailsVo =  gpProductionDetailsService.getVoById(gpDeliveryNoteVo.getProductionDetailsId());
            if (gpProductionDetailsVo != null) {
                gpIncomingInspect.setFollowUpName(gpProductionDetailsVo.getFollowUpName());
                gpIncomingInspect.setOperatorTime(now);
                gpIncomingInspect.setCodingSpecifications(gpProductionDetailsVo.getCodingSpecifications());
                gpIncomingInspect.setTagSpecifications(gpProductionDetailsVo.getTagSpecifications());
            }

            gpProductionSchedulingVo=gpProductionSchedulingService.getVoById(gpDeliveryNoteVo.getProductionSchedulingId());
            if (gpProductionSchedulingVo != null) {
                gpIncomingInspect.setIncomingTime(gpProductionSchedulingVo.getReturnTime());
            }

            // 获取克重规则配置 标准幅宽
            GpWeightReductionRuleSetting one = iGpWeightReductionRuleSettingService.getOne(new LambdaQueryWrapper<GpWeightReductionRuleSetting>().eq(GpWeightReductionRuleSetting::getProductName, gpProductionDetailsVo.getProductName()).eq(GpWeightReductionRuleSetting::getDelStatus, YesNoEnum.NO.getKey()));
            if (one!=null){
                gpIncomingInspect.setStandardWidth(one.getStandardWidth());
            }

            gpIncomingInspect.setSn(generateOrderNumber());

            gpIncomingInspectList.add(gpIncomingInspect);
        }

        boolean saveBatch = gpIncomingInspectService.saveBatch(gpIncomingInspectList);
        if (saveBatch) {
            this.createSubList(gpIncomingInspectList);
        }
        return saveBatch;
    }

    // 保存子表信息
    private void createSubList(List<GpIncomingInspect> gpIncomingInspectList) {
        for (GpIncomingInspect gpIncomingInspect : gpIncomingInspectList) {
            GpIncomingInspectYardVerify gpIncomingInspectYardVerify;
            GpIncomingInspectWidth gpIncomingInspectWidth;
            GpIncomingInspectWeight gpIncomingInspectWeight;
            for (int i = 0; i < 5; i++) {
                // 初始化验码
                gpIncomingInspectYardVerify = new GpIncomingInspectYardVerify();
                gpIncomingInspectYardVerify.setIncomingInspectId(gpIncomingInspect.getId());
                iGpIncomingInspectYardVerifyService.save(gpIncomingInspectYardVerify);
                // 初始化重量
                gpIncomingInspectWeight = new GpIncomingInspectWeight();
                gpIncomingInspectWeight.setIncomingInspectId(gpIncomingInspect.getId());
                iGpIncomingInspectWeightService.save(gpIncomingInspectWeight);
            }
            for (int j = 0; j < 3; j++) {
                // 初始化幅宽
                gpIncomingInspectWidth = new GpIncomingInspectWidth();
                gpIncomingInspectWidth.setIncomingInspectId(gpIncomingInspect.getId());
                iGpIncomingInspectWidthService.save(gpIncomingInspectWidth);
            }
        }
    }


    //生成订单号 格式  yy-MM-dd-序号 序号第二天归零
    public  String generateOrderNumber() {

        LocalDate lastDate = null;  // 上次生成订单号的日期
        int orderCount = 0;  // 订单序号
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        // 判断是否为新的一天，如果是则将序号归零
        if (lastDate == null || !currentDate.isEqual(lastDate)) {
            orderCount = 0;
            lastDate = currentDate;
        }

        // 格式化日期为字符串，年份只保留后两位
        String formattedDate = currentDate.format(DateTimeFormatter.ofPattern("yy-MM-dd"));

        // 生成序号（这里简化处理，每次调用序号加1）
        orderCount++;

        // 拼接订单号
        String orderNumber = formattedDate + "-" + orderCount;

        return orderNumber;
    }

    /**
     * 生成生产到货单
     * @param ids
     * @param createBy
     * @return
     */
    @Override
    @Transactional
    public boolean createDeliveryNote(List<Long> ids, String createBy) {
        List<GpDeliveryNote> list = new ArrayList<>();
        GpProductionScheduling gpProductionScheduling;
        for (Long id : ids) {
            gpProductionScheduling = gpProductionSchedulingService.getById(id);
            gpProductionScheduling.setDeliveryNoteFlag(YesNoEnum.YES.getKey());
            gpProductionScheduling.setReturnTime(new Date());
            gpProductionSchedulingService.updateById(gpProductionScheduling);
            GpDeliveryNote gpDeliveryNote = Convert.convert(new TypeReference<GpDeliveryNote>() {}, gpProductionScheduling);

            if (StringUtils.isNotBlank(createBy)) {
                gpDeliveryNote.setCreateBy(createBy);
            }
            GpProductionDetails gpProductionDetails = iGpProductionDetailsService.getById(gpProductionScheduling.getProductionDetailsId());
            if (gpProductionDetails != null && gpProductionDetails.getLogistics() !=null){
                gpDeliveryNote.setLogistics(gpProductionDetails.getLogistics());
            }

            this.init(gpDeliveryNote, gpProductionScheduling);
            list.add(gpDeliveryNote);
        }
        return this.saveBatch(list);
    }

    @Override
    public boolean edit(List<GpDeliveryNoteUpdate> list) {
        List<GpDeliveryNote> updateList = new ArrayList<>();
        GpProductionScheduling gpProductionScheduling;
        for (GpDeliveryNoteUpdate gpDeliveryNoteUpdate : list) {
            //判断到货单订单号是否重复
            //List<GpDeliveryNote> gpDeliveryNotes = this.list(new QueryWrapper<GpDeliveryNote>());
            //for (GpDeliveryNote gpDeliveryNote : gpDeliveryNotes) {
            //    //if(gpDeliveryNote.getSn().equals(gpDeliveryNoteUpdate)){
            //    //    throw new BaseException("到货单订单号重复");
            //    //}
            //}
            GpDeliveryNote gpDeliveryNote = Convert.convert(new TypeReference<GpDeliveryNote>() {}, gpDeliveryNoteUpdate);
            gpProductionScheduling = gpProductionSchedulingService.getById(gpDeliveryNote.getProductionSchedulingId());
            this.init(gpDeliveryNote, gpProductionScheduling);
            //计算大小条做成一栏 如98+100+98=总大小条数
            if (gpDeliveryNoteUpdate.getSizeBarOne()!=null ){
                //计算过程
                gpDeliveryNote.setSizeBarOne(gpDeliveryNoteUpdate.getSizeBarOne());
                //大小条
                gpDeliveryNote.setSizeBar(gpDeliveryNoteUpdate.getSizeBar());

            }

            if (gpDeliveryNoteUpdate.getQuantity()!=null && gpDeliveryNoteUpdate.getExFactorySpecifications()!=null){
                //总码数= （（条数-1）*规格）+大小条数
                gpDeliveryNote.setTotalQuantity(((gpDeliveryNoteUpdate.getQuantity() - 1) * gpDeliveryNoteUpdate.getExFactorySpecifications())+gpDeliveryNote.getSizeBar());
            }
            //更新排单表数据
            this.updateProductionScheduling(gpDeliveryNote);
            updateList.add(gpDeliveryNote);
        }
        return this.updateBatchById(updateList);
    }

    private void updateProductionScheduling(GpDeliveryNote gpDeliveryNote) {
        GpProductionScheduling gpProductionScheduling = gpProductionSchedulingService.getById(gpDeliveryNote.getProductionSchedulingId());
        //判断排单订单号是否重复
        if (StringUtils.isNotBlank(gpDeliveryNote.getSn())) {
            List<GpProductionScheduling> gpProductionSchedulingList = gpProductionSchedulingService.list(new QueryWrapper<GpProductionScheduling>());
            //for (GpProductionScheduling gpProductionScheduling1 : gpProductionSchedulingList) {
            //    if (gpDeliveryNote.getSn().equals(gpProductionScheduling1.getSn())){
            //        throw new BaseException("生产排单订单号重复");
            //    }
            //}
        }
        //修改排单表数据
        gpProductionScheduling.setReturnTime(gpDeliveryNote.getSendOutGoodsTime());
        gpProductionScheduling.setSupplierName(gpDeliveryNote.getSupplierName());
        gpProductionScheduling.setDyeingFactoryName(gpDeliveryNote.getDyeingFactoryName());
        gpProductionScheduling.setProductName(gpDeliveryNote.getProductName());
        gpProductionScheduling.setColour(gpDeliveryNote.getColour());
        gpProductionSchedulingService.updateById(gpProductionScheduling);

        //修改做货明细
        GpProductionDetails gpProductionDetails = gpProductionDetailsService.getById(gpDeliveryNote.getProductionDetailsId());
        gpProductionDetails.setSupplierName(gpDeliveryNote.getSupplierName());
        gpProductionDetails.setDyeingFactoryName(gpDeliveryNote.getDyeingFactoryName());
        gpProductionDetails.setProductName(gpDeliveryNote.getProductName());
        gpProductionDetails.setColour(gpDeliveryNote.getColour());
        gpProductionDetailsService.updateById(gpProductionDetails);

    }


    @Override
    public boolean editOne(GpDeliveryNoteUpdate gpDeliveryNoteUpdate) {
        GpDeliveryNote gpDeliveryNote = Convert.convert(new TypeReference<GpDeliveryNote>() {}, gpDeliveryNoteUpdate);
        GpProductionScheduling gpProductionScheduling = gpProductionSchedulingService.getById(gpDeliveryNote.getProductionSchedulingId());
        this.init(gpDeliveryNote, gpProductionScheduling);
        return this.updateById(gpDeliveryNote);
    }

    @Override
    public boolean copy(Long id, Integer copyNum) {
        GpDeliveryNote gpDeliveryNote = this.getById(id);
        if (gpDeliveryNote == null) {
            return false;
        }
        for (int i = 0; i < copyNum; i++) {
            gpDeliveryNote.setId(null);
            gpDeliveryNote.setSn(this.getSn());
            this.save(gpDeliveryNote);
        }
        return true;
    }

    private GpDeliveryNote init(GpDeliveryNote gpDeliveryNote, GpProductionScheduling gpProductionScheduling) {
        gpDeliveryNote.setSendOutGoodsTime(gpProductionScheduling.getReturnTime());
        gpDeliveryNote.setProductionSchedulingId(gpProductionScheduling.getId());
        // 如果批号不存在，且有染厂名称、发货日期、订单号都有，生成批号（根据染厂的字母代表+发货年月日+分缸的-1、-2、-3）
        if (StringUtils.isBlank(gpDeliveryNote.getBatchNo())
                && gpDeliveryNote.getDyeingFactoryId() != null
                && gpDeliveryNote.getSendOutGoodsTime() != null
                && StringUtils.isNotBlank(gpDeliveryNote.getSn())) {
            String batchNo = "";
            GpDyeingFactory gpDyeingFactory = iGpDyeingFactoryService.getById(gpDeliveryNote.getDyeingFactoryId());
            if (gpDyeingFactory != null && StringUtils.isNotBlank(gpDyeingFactory.getCode())) {
                batchNo += gpDyeingFactory.getCode();
            }
            String yyMMdd = DateUtils.parseDateToStr("yyMMdd", gpDeliveryNote.getSendOutGoodsTime());
            batchNo += yyMMdd;
            String dyeVatNo = gpProductionScheduling.getSn().substring(gpDeliveryNote.getSn().lastIndexOf("-"));
            batchNo += dyeVatNo;
            gpDeliveryNote.setBatchNo(batchNo);
            gpDeliveryNote.setDyeVatNo(gpProductionScheduling.getDyeVatNo());
        }
        if (StringUtils.isBlank(gpDeliveryNote.getSn())) {
            gpDeliveryNote.setSn(this.getSn());
        }
        return gpDeliveryNote;
    }

    private String getSn() {
        String sn = "";

        String yyMMdd = DateUtils.getDate("yyMMdd");
        sn += yyMMdd;

        GpDeliveryNote gpDeliveryNote = this.getOne(new LambdaQueryWrapper<GpDeliveryNote>()
                .eq(GpDeliveryNote::getDelStatus, YesNoEnum.NO.getKey())
                .isNotNull(GpDeliveryNote::getSn)
                .gt(GpDeliveryNote::getCreateTime, DateUtils.getDate("yyyy-MM-dd 00:00:00"))
                .orderByDesc(GpDeliveryNote::getCreateTime)
                .last("limit 1"));
        if (gpDeliveryNote == null) {
            sn += "-1";
        } else {
            String substring = gpDeliveryNote.getSn().substring(gpDeliveryNote.getSn().lastIndexOf("-") + 1);
            int index = Integer.parseInt(substring) + 1;
            sn += "-" + index;
        }
        return sn;
    }
}
